package cn.t.facade.order;


import cn.t.constants.CommonConstants;
import cn.t.converter.order.ReconDTOConverter;
import cn.t.converter.order.ReconDetailDTOConverter;
import cn.t.core.exception.BizException;
import cn.t.core.facade.FacadeImpl;
import cn.t.core.mode.PageInfoDTO;
import cn.t.core.mode.PageQueryDTO;
import cn.t.dto.order.ExcelReconciliationAddDTO;
import cn.t.dto.order.ReconDTO;
import cn.t.core.enums.base.CommonError;
import cn.t.enums.order.ErrorEnum;
import cn.t.model.order.ReconDO;
import cn.t.model.order.ReconDetailDO;
import cn.t.model.user.CustomerFirmDO;
import cn.t.request.ReconciliationReq;
import cn.t.request.api.PushReconToNidecReq;
import cn.t.service.order.ReconDetailService;
import cn.t.service.order.ReconService;
import cn.t.service.user.CustomerFirmService;
import cn.t.utils.DateUtil;
import cn.t.vo.order.ReconciliationVO;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.event.AnalysisEventListener;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.math3.util.Pair;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.StringCodec;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 对账单表(Recon)服务编排
 */
@Slf4j
@Service
@AllArgsConstructor
public class ReconFacade extends FacadeImpl<ReconDTO, ReconDO, ReconDTOConverter, ReconService> {

    private final ReconDetailDTOConverter reconDetailDTOConverter;
    private final ReconDetailService reconDetailService;
    private final CustomerFirmService customerFirmService;
    private final RedissonClient redissonClient;

    public PageInfoDTO<ReconciliationVO> page(PageQueryDTO<ReconciliationReq> req) {
        ReconDO queryParam = this.converter.req2Do(req.getParam());
        List<ReconDO> list = this.service.findByModel(queryParam, req.getStart(), req.getPageSize(), "gmt_created", " desc");

        List<Long> firmIds = list.stream().map(ReconDO::getFirmId).collect(Collectors.toList());
        Map<Long, String> idNameMap = this.customerFirmService.getFirmIdNameMap(firmIds);

        List<ReconciliationVO> recons = list.stream().map(f -> this.converter.do2Vo(f, idNameMap.get(f.getFirmId()))).collect(Collectors.toList());

        long total = this.service.count(queryParam);

        return new PageInfoDTO<>(req.getPageNo(), req.getPageSize(), total, recons);
    }

    public void importReconciliation(MultipartFile file, Long firmId, String startDate, String endDate, AnalysisEventListener<ExcelReconciliationAddDTO> eventListener) {
        ReconDO reconDO = new ReconDO();
        reconDO.setFirmId(firmId);
        List<ExcelReconciliationAddDTO> excelDataList = new ArrayList<>();
        try {
            byte[] data = file.getBytes();
            excelDataList = EasyExcelFactory.read(new ByteArrayInputStream(data), eventListener).head(ExcelReconciliationAddDTO.class).ignoreEmptyRow(true).doReadAllSync();
            excelDataList = excelDataList.stream().filter(entity ->
                    StringUtils.hasText(entity.getWorkOrderSn()) || StringUtils.hasText(entity.getOrderSn()) || StringUtils.hasText(entity.getSkuCode())
            ).collect(Collectors.toList());

            if (excelDataList.size() > 5000) {
                throw new BizException(ErrorEnum.DATA_TO_MANY, "导入超过5000行,请酌情上传");
            }
            List<ExcelReconciliationAddDTO> collect = excelDataList.stream().filter(entity -> !CollectionUtils.isEmpty(entity.getErrorMessages())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(collect)) {
                throw new BizException(ErrorEnum.FILE_PARSE_ERROR, "文件内容有必填项未填，请完善后重新上传");
            }
        } catch (IOException e) {
            log.error("文件处理过程中IO 异常", e);
        }
        this.saveReconInfo(excelDataList, firmId, startDate, endDate);
    }

    private void saveReconInfo(List<ExcelReconciliationAddDTO> reconciliationAddList, Long firmId, String startDate, String endDate) {
        ReconDO reconDO = new ReconDO();
        String reconSn = "REC" + DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now());
        reconDO.setReconSn(reconSn);
        reconDO.setFirmId(firmId);
        reconDO.setGmtStart(DateUtil.startDate(startDate));
        reconDO.setGmtEnd(DateUtil.startDate(endDate));
        // 保存对账主表信息
        this.service.addAndReturnId(reconDO);
        // 保存对账明细信息
        List<ReconDetailDO> reconDetailDOS = reconciliationAddList.stream().map(f -> this.reconDetailDTOConverter.excelDto2Do(f, reconSn)).collect(Collectors.toList());
        reconDetailService.addBatch(reconDetailDOS);
    }

    public Boolean pushToCustomer(Long id) {

        ReconDO recon = this.service.findById(id);

        // 查询对账单对应的客户号
        CustomerFirmDO customerFirmDO = this.customerFirmService.findById(recon.getFirmId());

        if (customerFirmDO == null || !StringUtils.hasText(customerFirmDO.getFirmCode())) {
            return false;
        }

        RMap<String, String> rMap = redissonClient.getMap(CommonConstants.CUSTOMER_RECON_PUSH_ADDR, new StringCodec());
        if (!rMap.containsKey(customerFirmDO.getFirmCode())) {
            return false;
        }

        return false;
    }






    public ReconciliationVO getBaseInfo(Long id) {
        ReconDO recon = this.service.findById(id);
        Map<Long, String> idNameMap = this.customerFirmService.getFirmIdNameMap(Lists.newArrayList(recon.getFirmId()));
        return this.converter.do2Vo(recon, idNameMap.get(recon.getFirmId()));
    }
}

